package com.syf.config.resource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.util.FileCopyUtils;

/**
 * 资源服务器配置：
 *      token验证
 *      授权路径拦截/放行，JWT存储token
 *
 * 我们的每个应用都是一个资源服务器，外部访问都需要 token 才能进行
 *
 *
 *  coin-iass基础服务使用的JWT:
 *      负责认证外部访问后台的token验证
 *  资源服务器:
 *      内部访问资源认证token
 *  eg:
 *      网关放行(/user/users/register) -> 资源服务器放行(/gt/register)
 */
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.
            csrf().disable()    //由于使用的是 JWT，我们这里不需要 csrf
            .sessionManagement().disable() // 基于 token，所以不需要 session
            .authorizeRequests()
            .antMatchers(
                    "/markets/klink/**",
                    "/users/setPassword" , //会员重置密码(忘记密码)
                    "/users/register", //会员的注册
                    "/sms/sendTo", //会员短信验证码发送
                    "/gt/register" , //放行极验(图形验证码)访问
                    "/login" ,  //登录放行
                    "/v2/api-docs",
                    "/swagger-resources/configuration/ui",//用来获取支持的动作
                    "/swagger-resources",//用来获取api-docs的URI
                    "/swagger-resources/configuration/security",//安全选项
                    "/webjars/**",
                    "/swagger-ui.html"
            ).permitAll() //授权放行
            .antMatchers("/**").authenticated() //拦截所有请求，都需要认证之后才行
            .and().headers().cacheControl();
    }

    /**
     * 设置公钥:
     *      resource 验证token（公钥） , authorization 产生 token （私钥）
     *
     * @param resources
     * @throws Exception
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(jwtTokenStore());

    }

    private TokenStore jwtTokenStore() {
        JwtTokenStore jwtTokenStore = new JwtTokenStore(accessTokenConverter()); //JWT存储token
        return jwtTokenStore;
    }

    @Bean // 放在ioc容器的
    public JwtAccessTokenConverter accessTokenConverter() {
        //resource 验证token（公钥） , authorization 产生 token （私钥）
        JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
        String s = null;
        try {
            ClassPathResource classPathResource = new ClassPathResource("coinexchange.txt"); //token公钥
            byte[] bytes = FileCopyUtils.copyToByteArray(classPathResource.getInputStream()); //txt文件 -> 字节
            s = new String(bytes, "UTF-8");  //字节 -> String
        } catch (Exception e) {
            e.printStackTrace();
        }
        tokenConverter.setVerifierKey(s);  //验证token（公钥）
        return tokenConverter;
    }
}
